package com.hex.ds.hdtp.core.inf.data.contrast.service.impl;

import com.hex.ds.hdtp.core.inf.common.utils.JdbcConnectUtil;
import com.hex.ds.hdtp.core.inf.metadata.entity.TableFieldsEntity;
import com.hex.ds.hdtp.core.inf.metadata.po.SourceConfInfoPo;
import com.hex.ds.hdtp.core.inf.metadata.repository.ISourceConfInfoRepository;
import com.hex.ds.hdtp.core.inf.metadata.service.impl.GaussMethodService;
import com.hex.ds.hdtp.core.inf.metadata.service.impl.SourceMethodHandlerContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.sql.SQLException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
@Service("COMPARE_GAUSS")
public class GaussInfoService extends AbstractDataInfoService {
    private final GaussMethodService gaussMethodService;

    public GaussInfoService(ISourceConfInfoRepository sourceConfInfoRepository, SourceMethodHandlerContext sourceMethodHandlerContext, GaussMethodService gaussMethodService) {
        super(sourceConfInfoRepository, sourceMethodHandlerContext);
        this.gaussMethodService = gaussMethodService;
    }

    public Boolean selectTableExist(String sourceCode, String schema, String table) throws SQLException {
        List<SourceConfInfoPo> sourceConfInfoPoList = getSourceConfInfoRepository().queryListBySourceCode(sourceCode);
        return JdbcConnectUtil.getTableExist(sourceConfInfoPoList, table.toLowerCase());
    }

    /**
     * @Method selectPartitionField
     * @Param
     * @Param sourceCode
     * @Param schema
     * @Param table
     * @Return java.util.List<java.lang.String>
     * @Description 分区字段
     * @Author xin.zhao
     * @Date 2023/9/5 9:28
     * @Version V1.0
     */
    @Override
    public List<String> selectPartitionField(String sourceCode, String schema, String table) throws SQLException {
        List<SourceConfInfoPo> sourceConfInfoPoList = getSourceConfInfoRepository().queryListBySourceCode(sourceCode);
        String querySql = gaussMethodService.getTablePartitionFieldSql(schema, table);
        String stringResult = JdbcConnectUtil.getStringResult(sourceConfInfoPoList, querySql);
        List<String> strings = extractPartitionFields(stringResult);
        return strings;
    }


    @Override
    public String buildCreateTableSql(List<TableFieldsEntity> tableFieldsEntities, List<String> partitionFieldName, String isCover) {
        //sql头
        String header = getHeader(isCover, tableFieldsEntities);
        //sql体
        String fileds = getFiled(tableFieldsEntities, partitionFieldName);
        //sql分区字段和中文备注
        String footer = getFooter(tableFieldsEntities, partitionFieldName);
        return header + fileds + footer;
    }

    /**
     * @Method getHeader
     * @Param
     * @Param isCover
     * @Param tableFieldsEntities
     * @Return java.lang.String
     * @Description sql头的拼接
     * @Author xin.zhao
     * @Date 2023/9/4 17:43
     * @Version V1.0
     */
    public String getHeader(String isCover, List<TableFieldsEntity> tableFieldsEntities) {
        // 是否覆盖建表
        String dropSQL = "";
        if (isCover.equals("1")) {
            dropSQL = gaussMethodService.getDropTableSql(tableFieldsEntities.get(0).getDataBaseName(), tableFieldsEntities.get(0).getTableName());
        }
        // 建表SQL头
        String createSqlHeader = gaussMethodService.getCreateTableHeaderSql(tableFieldsEntities.get(0).getDataBaseName(), tableFieldsEntities.get(0).getTableName());
        return dropSQL + createSqlHeader;
    }

    /**
     * @Method getFiled
     * @Param
     * @Param tableFieldsEntities
     * @Param partitionFieldName
     * @Return java.lang.String
     * @Description sql字段拼接
     * @Author xin.zhao
     * @Date 2023/9/4 17:43
     * @Version V1.0
     */
    public String getFiled(List<TableFieldsEntity> tableFieldsEntities, List<String> partitionFieldName) {
        // 建表SQL体--字段信息
        StringBuilder createSqlBody = new StringBuilder();
        //排查与分区字段同名字段
        for (TableFieldsEntity t : tableFieldsEntities) {
            if (partitionFieldName.contains(t.getColumnName())) {
                t.setColumnName(t.getColumnName() + "SRC");
            }
        }
        //拼接字段
        for (TableFieldsEntity tableFields : tableFieldsEntities) {
            createSqlBody.append(gaussMethodService.getCreateTableBodySql(
                    tableFields.getColumnName(),
                    tableFields.getColumnType(),
                    (tableFields.getColumnLength() != null && !tableFields.getColumnLength().equals("0")) ? "(" + tableFields.getColumnLength() + ")" : ""
                    /*tableFields.getColumnCommet() != null ? String.format(DataInfoSQL.GAUSS_CREATE_SQL_BODY_COMMENT.getValue(), tableFields.getColumnCommet()) : ""*/
            ));
        }
        //增加分区字段
        for (String s : partitionFieldName) {
            createSqlBody.append(gaussMethodService.getCreateTableBodySql(s, "INTEGER", ""));
        }
        // 建表SQL--尾括号
        String createSqlFooter = String.format(") \n");
        return createSqlBody.toString().substring(0, createSqlBody.lastIndexOf(",")).trim() + createSqlFooter;
    }

    /**
     * @Method getFooter
     * @Param
     * @Param tableFieldsEntities
     * @Param partitionFieldName
     * @Return java.lang.String
     * @Description 分区字段与中文注释
     * @Author xin.zhao
     * @Date 2023/9/4 17:44
     * @Version V1.0
     */
    public String getFooter(List<TableFieldsEntity> tableFieldsEntities, List<String> partitionFieldName) {
        LocalDate now = LocalDate.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        String format = now.format(formatter);
        // 建表SQL--分区字段
        StringBuilder partitionField = new StringBuilder();
        partitionFieldName.forEach(fieldName -> {
            partitionField.append(gaussMethodService.getCreateTablePartitionSql(fieldName)).append(gaussMethodService.getCreateTablePartitionSuffixSql(format));
        });
        //建表SQL--尾引号
        String createSqlFast = String.format(";\n");
        //拼接中文注释
        StringBuilder annotateField = new StringBuilder();
        for (TableFieldsEntity t : tableFieldsEntities) {
            if (t.getColumnCommet() != null) {
                annotateField.append(gaussMethodService.getCreateTableCommentSql(t.getDataBaseName(), t.getTableName(), t.getColumnName(), t.getColumnCommet()));
            }
        }
        return partitionField + createSqlFast + annotateField;
    }

    /**
     * @Method extractPartitionFields
     * @Param
     * @Param createTableStatement
     * @Return
     * @Description 正则匹配字符串拿出分区字段
     * @Author xin.zhao
     * @Date 2023/9/5 11:20
     * @Version V1.0
     */
    public static List<String> extractPartitionFields(String createTableStatement) {
        List<String> partitionFields = new ArrayList<>();

        Pattern pattern = Pattern.compile("PARTITION BY RANGE \\((.*?)\\)");
        Matcher matcher = pattern.matcher(createTableStatement);

        if (matcher.find()) {
            String s = matcher.group(1);
            String partitionClause = s.toUpperCase();
            partitionFields = Arrays.asList(partitionClause.split(","));
        }

        return partitionFields;
    }


    @Override
    protected String selectDataNumSql(String schema, String table, String whereSql) {
        return gaussMethodService.getTableDataNumSql(schema, table, whereSql);
    }

    @Override
    protected String selectCountSumIsNullSql(String schema, String table, String field, String whereSql) {
        if (whereSql != null && whereSql.trim().toUpperCase().startsWith("WHERE")) {
            whereSql = "AND " + whereSql.trim().substring(5);
        }
        return gaussMethodService.getTableIsNullCountSql(schema, table, field, whereSql);
    }
}


